/*
    libnbds
    Non-blocking Data Structures Library

    Copyright (C) 2011 Paweł Dziepak

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef NBDS_VECTOR_H
#define NBDS_VECTOR_H

namespace nbds {
	class vector_base {
	protected:
		struct buffer {
			void **data;

			unsigned int last_idx;
			unsigned int size;
		};

		buffer *current;

		vector_base();
		vector_base(unsigned int size);
		~vector_base();

		void push_back_(void *);
		void *get_(unsigned int);

		int count_();
		bool is_empty_();		
	};

	template<typename T>
	class vector : public vector_base {
	public:
		class iterator {
		private:
			unsigned int idx;
			vector<T> &obj;
		public:
			iterator(vector<T> *o, unsigned int i) :
				idx(i), obj(*o) { }

			iterator(const iterator &x) :
				idx(x.idx), obj(x.obj) { }

			T &operator*() {
				return obj[idx];
			}

			T *operator->() {
				return &obj[idx];
			}

			iterator &operator=(const iterator &x) {
				idx = x.idx;
				obj = x.obj;

				return *this;
			}

			iterator &operator++() {
				idx++;

				return *this;
			}

			iterator operator++(int) {
				iterator it = *this;
				idx++;
				return it;
			}

			iterator &operator--() {
				idx--;

				return *this;
			}

			iterator operator--(int) {
				iterator it = *this;
				idx--;
				return it;
			}
		};

		vector() { }
		vector(unsigned int size) : vector_base(size) { }

		void push_back(const T &obj) {
			T *x = new T(obj);
			push_back_(reinterpret_cast<void*>(x));
		}

		T &operator[](unsigned int idx) {
			return *reinterpret_cast<T*>(get_(idx));
		}

		iterator begin() {
			return iterator(this, 0);
		}

		iterator end() {
			return iterator(this, current->last_idx);
		}

		int count() {
			return count_();
		}

		bool is_empty() {
			return is_empty_();
		}
	};
}

#endif
